/**
 * 并发任务限制器
 * 限制任务并发数量，用法与 promise.all() 类似
 * @param {*} taskList 任务列表
 * @param {*} maxThreadAmount 最大并行执行数量
 */
exports.parallelTaskLimiter = function (taskList, maxThreadAmount = 5) {
  return new Promise((resolve, reject) => {
    if (taskList.length === 0) {
      return reject("taskList 数量必须大于0");
    }
    if (maxThreadAmount <= 0) {
      return reject("maxThreadAmount 必须大于1");
    }
    const result = [];
    const taskQueue = [];
    let activeThreadAmount = 0;
    let tid = 0;

    // 包装任务
    function packingTask(task, taskId) {
      activeThreadAmount++;
      return task()
        .then((res) => (result[taskId] = res))
        .catch((err) => (result[taskId] = err))
        .finally(() => {
          activeThreadAmount--;

          // 提取下一个任务并执行
          const next = taskQueue.shift();
          if (next) {
            next();
          }

          // 所有任务执行完毕后执行 resolve
          if (taskQueue.length === 0 && activeThreadAmount === 0) {
            resolve(result);
          }
        });
    }

    // 注册任务
    for (const task of taskList) {
      if (activeThreadAmount < maxThreadAmount) {
        packingTask(task, tid++);
      } else {
        taskQueue.push(packingTask.bind(null, task, tid++));
      }
    }
  });
};
